package com.boarsoft.config.yaml;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.amihaiemil.eoyaml.Yaml;
import com.amihaiemil.eoyaml.YamlMapping;
import com.amihaiemil.eoyaml.YamlNode;

/**
 * yml与其他各种格式之间互转
 * <p>
 * <ul>
 * <li>1.yml 转 properties</li>
 * <li>2.properties 转 yml</li>
 * <li>3.yml 转 json</li>
 * <li>4.json 转 yml</li>
 * <li>5.yml 转 map</li>
 * <li>6.map 转 yml</li>
 * <li>7.yml 转 kvList</li>
 * <li>8.kvList 转 yml</li>
 * <li>9.kv 转 map</li>
 * <li>10.kv 转 properties</li>
 * <li>11.kv 转 yml</li>
 * </ul>
 *
 * @author shizi
 * @since 2020/9/14 3:17 下午
 */
public class YamlUtil {
	private static final Logger log = LoggerFactory.getLogger(YamlUtil.class);

	/** 注释标识 */
	private static final String REMARK_PRE = "# ";
	/** 换行符 */
	private static final String PROPERTY_NEW_LINE = "\n";
	/** 缩进空格 */
	private static final String INDENT_BLANKS = "  ";
	/** 分号连接符 */
	private static final String SIGN_SEMICOLON = ":";
	/** 等号连接符 */
	private static final String SIGN_EQUAL = "=";
	/** 点 */
	private static final String DOT = ".";
	/** yaml 数组缩进 */
	private static final String ARRAY_BLANKS = "- ";
	/** yaml的value换行符 */
	private static final String yaml_NEW_LINE_DOM = "|\n";
	private static final Pattern rangePattern = Pattern.compile("^(.*)\\[(\\d*)\\]$");

	public static boolean isYaml(String yamlContent) {
		if (null == yamlContent || "".equals(yamlContent)) {
			return false;
		}
		try {
			yamlToProperties(yamlContent);
			return true;
		} catch (RuntimeException e) {
			log.error("不是严格yaml类型，因为异常：", e);
			return false;
		}
	}

	public static boolean isProperties(String propertiesContent) {
		if (null == propertiesContent || "".equals(propertiesContent)) {
			return false;
		}
		try {
			return isYaml(propertiesToYaml(propertiesContent));
		} catch (RuntimeException e) {
			log.error("不是严格properties类型，因为异常：", e);
			return false;
		}
	}

	public static boolean isJson(String jsonContent) {
		try {
			JSON.parseObject(jsonContent);
			return true;
		} catch (Throwable e) {
			log.error("不是严格json类型，因为异常：", e);
			return false;
		}
	}

	/**
	 * yaml格式转换到properties
	 */
	public static String yamlToProperties(String yamlContent) {
		try {
			if (null == yamlContent || "".equals(yamlContent)) {
				return null;
			}

			List<String> propertiesList = new ArrayList<>();
			Map<String, String> remarkMap = new LinkedHashMap<>();
			Map<String, Object> valueMap = yamlToMap(yamlContent);

			// 读取yaml的注释
			yamlToRemarkMap(remarkMap, Yaml.createYamlInput(yamlContent).readYamlMapping(), "");
			formatYamlToProperties(propertiesList, remarkMap, valueMap, "");
			return propertiesList.stream().filter(e -> null != e && !"".equals(e)).reduce((a, b) -> a + PROPERTY_NEW_LINE + b)
					.orElse("");
		} catch (Throwable e) {
			log.error("yamlToProperties error, yamlContent={}", yamlContent);
			throw new RuntimeException("yaml 转换到 properties异常", e);
		}
	}

	/**
	 * properties 转换到 yaml
	 */
	public static String propertiesToYaml(Properties properties) {
		StringBuilder sb = new StringBuilder();
		properties.forEach((k, v) -> {
			sb.append(k).append("=").append(v).append(PROPERTY_NEW_LINE);
		});
		return propertiesToYaml(sb.toString());
	}

	/**
	 * properties 转换到 yaml
	 */
	public static String propertiesToYaml(String propertiesContent) {
		if (null == propertiesContent || "".equals(propertiesContent)) {
			return null;
		}
		try {
			List<String> yamlLineList = new ArrayList<>();
			List<String> propertiesLineWordList = getPropertiesItemLineList(propertiesContent);

			List<MyYamlNode> yamlNodes = new ArrayList<>();
			StringBuilder projectRemark = new StringBuilder();
			StringBuilder remark = new StringBuilder();
			for (String line : propertiesLineWordList) {
				line = line.trim();
				if (!"".equals(line)) {
					if (line.startsWith("#")) {
						if (0 != remark.length()) {
							projectRemark.append(remark.toString());
							remark.delete(0, remark.length());
						}
						remark.append(line);
						continue;
					}
					int index = line.indexOf("=");
					String key = line.substring(0, index);
					String value = line.substring(index + 1);
					// 对于yaml中换行的添加|用于保留换行
					if (value.contains("\n")) {
						value = yaml_NEW_LINE_DOM + value;
					}

					final List<String> lineWordList = new ArrayList<>(Arrays.asList(key.split("\\.")));
					wordToNode(lineWordList, yamlNodes, null, false, null, appendSpaceForArrayValue(value),
							projectRemark.toString(), remark.toString());

					// 删除本地保留
					remark.delete(0, remark.length());
					projectRemark.delete(0, projectRemark.length());
				}
			}
			formatPropertiesToYaml(yamlLineList, yamlNodes, false, "");
			String originalYaml = yamlLineList.stream().reduce((a, b) -> a + "\n" + b).orElse("") + "\n";

			// 给yaml的顶层点添加上层换行
			return appendNextLine(originalYaml);
		} catch (Throwable e) {
			log.error("propertiesToyaml error, propertiesContent={}", propertiesContent);
			throw new RuntimeException("properties 转换到 yaml异常", e);
		}
	}

	/**
	 * yaml 转 map
	 *
	 * 由于eo-yaml对map转换支持会默认将一些key添加字符，这里就用snakeyaml工具做
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Map<String, Object> yamlToMap(String yamlContent) {
		if (null == yamlContent || "".equals(yamlContent)) {
			return new HashMap<>();
		}
		try {
			Map<String, Object> resultMap = new HashMap<>();
			org.yaml.snakeyaml.Yaml yml = new org.yaml.snakeyaml.Yaml();
			Map result = yml.load(yamlContent);
			Set<Map.Entry<?, ?>> entrySet = result.entrySet();
			for (Map.Entry<?, ?> entry : entrySet) {
				resultMap.put(String.valueOf(entry.getKey()), entry.getValue());
			}
			return resultMap;
		} catch (Throwable e) {
			log.error("ymlToMap error, yamlContent={}", yamlContent, e);
			throw new RuntimeException("yml 转换到 map 异常", e);
		}
	}

	/**
	 * map 转 yaml
	 */
	public static String mapToYaml(Map<String, Object> mapData) {
		if (null == mapData || mapData.isEmpty()) {
			return null;
		}

		try {
			org.yaml.snakeyaml.Yaml yaml = new org.yaml.snakeyaml.Yaml();
			String originalYaml = yaml.dumpAsMap(mapData);
			// 由于snakeyaml对数组缩进支持不够好，这里做一层缩进
			originalYaml = yamlFormatToAppendArray(originalYaml);

			return appendNextLine(originalYaml);
		} catch (Throwable e) {
			log.error("mapToYml error, mapData={}", mapData);
			throw new RuntimeException("map 转换到 yml 异常", e);
		}
	}

	/**
	 * yaml 转 json
	 */
	public static String yamlToJson(String yamlContent) {
		if (null == yamlContent || "".equals(yamlContent)) {
			return null;
		}
		try {
			return JSON.toJSONString(yamlToMap(yamlContent));
		} catch (Throwable e) {
			log.error("yamlToJson error, yamlContent={}", yamlContent);
			throw new RuntimeException("yaml 转换到 json 异常", e);
		}
	}

	/**
	 * json 转 yaml
	 */
	public static String jsonToYaml(String jsonContent) {
		if (null == jsonContent || "".equals(jsonContent)) {
			return null;
		}
		try {
			return mapToYaml(JSON.parseObject(jsonContent));
		} catch (Throwable e) {
			log.error("jsonToYaml error, jsonContent={}", jsonContent);
			throw new RuntimeException("json 转换到 yaml 异常", e);
		}
	}

	/**
	 * yaml类型转换为 k-v的集合
	 */
	public static List<Map.Entry<String, String>> yamlToKVList(String yamlContent) {
		if (null == yamlContent || "".equals(yamlContent)) {
			return Collections.emptyList();
		}
		try {
			String propertiesContent = yamlToProperties(yamlContent);
			return getPropertiesItemLineList(propertiesContent).stream().map(e -> {
				int index = e.indexOf("=");
				String key = e.substring(0, index);
				String value = e.substring(index + 1);
				return new AbstractMap.SimpleEntry<>(key, value);
			}).collect(Collectors.toList());
		} catch (Throwable e) {
			log.error("yamlToKVList error, yamlContent={}", yamlContent);
			throw new RuntimeException("yaml 转换到 kv-list 异常", e);
		}
	}

	/**
	 * k-v的集合类型转yaml
	 */
	public static String kvListToYaml(List<Map.Entry<String, Object>> kvStringList) {
		if (null == kvStringList || kvStringList.isEmpty()) {
			return null;
		}
		try {
			String propertiesContent = kvStringList.stream().map(e -> e.getKey() + "=" + e.getValue())
					.reduce((a, b) -> a + "\n" + b).orElse("");
			return propertiesToYaml(propertiesContent);
		} catch (Throwable e) {
			log.error("kvListToYaml error, kvStringList={}", kvStringList);
			throw new RuntimeException("kv-list 转换到 yaml 异常", e);
		}
	}

	public static String kvToYaml(String key, String value, ConfigValueTypeEnum valueTypeEnum) {
		if (null == key || "".equals(key)) {
			return null;
		}
		try {
			return propertiesToYaml(kvToProperties(key, value, valueTypeEnum));
		} catch (Throwable e) {
			log.error("kvToyaml error, key={}, value={}, valueType={}", key, value, valueTypeEnum);
			throw new RuntimeException("kv 转换到 yaml 异常", e);
		}
	}

	public static Map<String, Object> kvToMap(String key, String value, ConfigValueTypeEnum valueTypeEnum) {
		if (null == key || "".equals(key)) {
			return null;
		}
		try {
			Map<String, Object> dataMap = new HashMap<>();
			switch (valueTypeEnum) {
			case YAML:
				return yamlToMap(value);
			case JSON:
				return JSON.parseObject(value);
			case PROPERTIES:
			case STRING:
				dataMap.put(key, value);
				return dataMap;
			default:
				return dataMap;
			}
		} catch (Throwable e) {
			log.error("kvToProperties error, key={}, value={}, valueType={}", key, value, valueTypeEnum.name(), e);
			throw new RuntimeException("kv 转换到 properties 异常", e);
		}
	}

	public static String kvToProperties(String key, String value, ConfigValueTypeEnum valueTypeEnum) {
		return kvToProperties(key, value, null, valueTypeEnum);
	}

	/**
	 * k-v的String类型转properties
	 *
	 * <p>
	 * 其中key可能是a.b.c这种，而value可能是各种各样的类型，我们这里通过valueType进行区分
	 *
	 * @param key
	 *            主键
	 * @param value
	 *            待转换的值
	 * @param desc
	 *            注释
	 * @param valueTypeEnum
	 *            值的类型，0：yaml，1：properties，2：json，3：string
	 * @return 转换之后的yaml类型
	 */
	public static String kvToProperties(String key, String value, String desc, ConfigValueTypeEnum valueTypeEnum) {
		if (null == key || "".equals(key)) {
			return null;
		}

		try {
			// 将value对应的值先转换为properties类型，然后对key进行拼接，最后再统一转化为yaml格式
			StringBuilder propertiesResult = new StringBuilder();
			if (null != desc && !"".equals(desc)) {
				propertiesResult.append("# ").append(desc).append("\n");
			}

			String propertiesValue = "";
			switch (valueTypeEnum) {
			case YAML:
				propertiesValue = yamlToProperties(value);
				break;
			case JSON:
				propertiesValue = yamlToProperties(jsonToYaml(value));
				break;
			case PROPERTIES:
				propertiesValue = value;
				break;
			case STRING:
				if (value.contains(":") || value.contains("=")) {
					return key + "=" + "'" + value + "'";
				} else {
					return key + "=" + value;
				}

			default:
				break;
			}

			propertiesValue = getPropertiesItemLineList(propertiesValue).stream().map(e -> {
				int index = e.indexOf("=");
				String keyTem = e.substring(0, index).trim();
				String valueTem = e.substring(index + 1).trim();
				return key + DOT + keyTem + "=" + valueTem;
			}).reduce((a, b) -> a + PROPERTY_NEW_LINE + b).orElse("");

			propertiesResult.append(propertiesValue);
			return propertiesResult.toString();
		} catch (Throwable e) {
			log.error("kvToProperties error, key={}, value={}, valueType={}", key, value, valueTypeEnum.name(), e);
			throw new RuntimeException("kv 转换到 properties 异常", e);
		}
	}

	/**
	 * 给yaml格式的内容中的数组部分多增一层缩进， eo-yaml格式解析比较严格
	 */
	private static String yamlFormatToAppendArray(String yamlContent) {
		StringBuilder sb = new StringBuilder();
		String[] items = yamlContent.split("\n");
		Integer blankSize = null;
		for (String item : items) {
			if (item.trim().startsWith("- ")) {
				int index = item.indexOf("- ");
				if (null == blankSize) {
					blankSize = item.substring(0, index).length();
					sb.append(INDENT_BLANKS).append(item).append("\n");
				} else {
					int itemBlank = item.substring(0, index).length();
					if (itemBlank > blankSize) {
						sb.append(INDENT_BLANKS).append(INDENT_BLANKS).append(item).append("\n");
					} else {
						sb.append(INDENT_BLANKS).append(item).append("\n");
					}
				}
			} else {
				if (null == blankSize) {
					sb.append(item).append("\n");
				} else {
					int itemBlankSize = item.substring(0, item.indexOf(item.trim())).length();
					if (itemBlankSize > blankSize) {
						sb.append(INDENT_BLANKS).append(item).append("\n");
					} else {
						sb.append(item).append("\n");
						blankSize = null;
					}
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 给yaml的头部key添加换行
	 */
	private static String appendNextLine(String yamlContent) {
		StringBuilder sb = new StringBuilder();
		String[] items = yamlContent.split("\n");
		boolean head = true;
		for (String item : items) {
			int itemBlankSize = item.substring(0, item.indexOf(item.trim())).length();
			if (0 == itemBlankSize) {
				if (head) {
					sb.append(item).append("\n");
					head = false;
				} else {
					sb.append("\n").append(item).append("\n");
				}
			} else {
				sb.append(item).append("\n");
			}
		}
		return sb.toString();
	}

	public static List<String> getPropertiesItemLineList(String propertiesContent) {
		if (null == propertiesContent) {
			return Collections.emptyList();
		}
		String[] lineList = propertiesContent.split(PROPERTY_NEW_LINE);
		List<String> itemLineList = new ArrayList<>();
		StringBuilder sb = new StringBuilder();
		for (String line : lineList) {
			// 处理多行数据
			if (line.endsWith("\\")) {
				sb.append(line).append("\n");
			} else {
				sb.append(line).append("\n");
				itemLineList.add(sb.toString());
				sb.delete(0, sb.length());
			}
		}
		return itemLineList;
	}

	/**
	 * 将key转换为yaml节点
	 *
	 * @param lineWordList
	 *            待转换的key，比如{@code k1.k2.k3=123}
	 * @param nodeList
	 *            已经保存的节点数据
	 * @param lastNodeArrayFlag
	 *            上一个节点是否数组类型
	 * @param index
	 *            索引下标
	 * @param value
	 *            解析的值
	 * @param remark
	 *            当前value对应的注释
	 */
	private static void wordToNode(List<String> lineWordList, List<MyYamlNode> nodeList, MyYamlNode parentNode,
			Boolean lastNodeArrayFlag, Integer index, String value, String projectRemark, String remark) {
		if (lineWordList.isEmpty()) {
			if (lastNodeArrayFlag) {
				MyYamlNode node = new MyYamlNode();
				node.setValue(value);
				node.setRemark(remark);
				nodeList.add(node);
			}
		} else {
			String nodeName = lineWordList.get(0);

			Map.Entry<String, Integer> nameAndIndex = peelArray(nodeName);
			nodeName = nameAndIndex.getKey();
			Integer nextIndex = nameAndIndex.getValue();

			MyYamlNode node = new MyYamlNode();
			node.setName(nodeName);
			node.setProjectRemark(projectRemark);
			node.setParent(parentNode);
			node.setRemark(remark);
			node.setLastNodeIndex(index);
			lineWordList.remove(0);

			// 如果节点下面的子节点数量为0，则为终端节点，也就是赋值节点
			if (lineWordList.size() == 0) {
				if (null == nextIndex) {
					node.setRemark(remark);
					node.setValue(value);
				}
			}

			// nextIndex 不空，表示当前节点为数组，则之后的数据为他的节点数据
			if (null != nextIndex) {
				node.setArrayFlag(true);
				boolean hasEqualsName = false;
				// 遍历查询节点是否存在
				for (MyYamlNode yn : nodeList) {
					// 如果节点名称已存在，则递归添加剩下的数据节点
					if (nodeName.equals(yn.getName()) && yn.getArrayFlag()) {
						Integer yamlNodeIndex = yn.getLastNodeIndex();
						if (null == yamlNodeIndex || index.equals(yamlNodeIndex)) {
							hasEqualsName = true;
							wordToNode(lineWordList, yn.getValueList(), node.getParent(), true, nextIndex,
									appendSpaceForArrayValue(value), null, remark);
						}
					}
				}
				// 如果遍历结果为节点名称不存在，则递归添加剩下的数据节点，并把新节点添加到上级yamlTree的子节点中
				if (!hasEqualsName) {
					wordToNode(lineWordList, node.getValueList(), node.getParent(), true, nextIndex,
							appendSpaceForArrayValue(value), null, remark);
					nodeList.add(node);
				}
			} else {
				boolean hasEqualsName = false;
				// 遍历查询节点是否存在
				for (MyYamlNode yamlNode : nodeList) {
					if (!lastNodeArrayFlag) {
						// 如果节点名称已存在，则递归添加剩下的数据节点
						if (nodeName.equals(yamlNode.getName())) {
							hasEqualsName = true;
							wordToNode(lineWordList, yamlNode.getChildren(), yamlNode, false, nextIndex,
									appendSpaceForArrayValue(value), null, remark);
						}
					} else {
						// 如果节点名称已存在，则递归添加剩下的数据节点
						if (nodeName.equals(yamlNode.getName())) {
							Integer yamlNodeIndex = yamlNode.getLastNodeIndex();
							if (null == yamlNodeIndex || index.equals(yamlNodeIndex)) {
								hasEqualsName = true;
								wordToNode(lineWordList, yamlNode.getChildren(), yamlNode, true, nextIndex,
										appendSpaceForArrayValue(value), null, remark);
							}
						}
					}
				}
				// 如果遍历结果为节点名称不存在，则递归添加剩下的数据节点，并把新节点添加到上级yamlTree的子节点中
				if (!hasEqualsName) {
					wordToNode(lineWordList, node.getChildren(), node, false, nextIndex, appendSpaceForArrayValue(value), null,
							remark);
					nodeList.add(node);
				}
			}
		}
	}

	/**
	 * 获取yaml中的注释
	 *
	 * @param remarkMap
	 *            解析后填充的注释map：key为a.b.c.d，value为对应的注释，去除掉前缀#后的数据
	 * @param mapping
	 *            yaml解析后数据
	 * @param prefix
	 *            前缀
	 */
	private static void yamlToRemarkMap(Map<String, String> remarkMap, YamlMapping mapping, String prefix) {
		if (null == mapping) {
			return;
		}
		for (YamlNode node : mapping.keys()) {
			String nodeName = node.asScalar().value();
			String remark = mapping.value(node).comment().value();

			if (null != remark && !"".equals(remark)) {
				remarkMap.put(wrapKey(prefix, nodeName), remark);
			}

			yamlToRemarkMap(remarkMap, mapping.yamlMapping(node), wrapKey(prefix, nodeName));
		}
	}

	private static String wrapKey(String prefix, String value) {
		if (null != prefix && !"".equals(prefix)) {
			return prefix + "." + value;
		}
		return value;
	}

	/**
	 * 解析节点名字，为数组则返回数组名和节点下标
	 * <p>
	 * name.test[0] 将test和0进行返回
	 * 
	 * @param nodeName
	 *            界面的名字
	 * @return 如果是数组，则将数组名和解析后的下标返回
	 */
	private static Map.Entry<String, Integer> peelArray(String nodeName) {
		String name = nodeName;
		Integer index = null;
		Matcher matcher = rangePattern.matcher(nodeName);
		if (matcher.find()) {
			String indexStr = matcher.group(2);
			if (null != indexStr) {
				index = Integer.valueOf(indexStr);
			}
			name = matcher.group(1);
		}

		return new AbstractMap.SimpleEntry<>(name, index);
	}

	/**
	 * 将yaml对应的这种value进行添加前缀空格，其中value为key1对应的value {@code
	 * test:
	 *   key1: |
	 *     value1
	 *     value2
	 *     value3
	 * } 对应的值 {@code
	 * |
	 *   value1
	 *   value2
	 *   value3
	 * }
	 *
	 * @param value
	 *            待转换的值比如{@code
	 *              test:
	 *              key1: |
	 *              value1
	 *              value2
	 *              value3
	 *              }
	 * @return 添加前缀空格之后的处理 {@code
	 * |
	 *   value1
	 *   value2
	 *   value3
	 * }
	 */
	private static String appendSpaceForArrayValue(String value) {
		if (!value.startsWith(yaml_NEW_LINE_DOM)) {
			return value;
		}
		String valueTem = value.substring(yaml_NEW_LINE_DOM.length());
		return yaml_NEW_LINE_DOM + Arrays.stream(valueTem.split("\\n")).map(e -> {
			String tem = e;
			if (e.endsWith("\\")) {
				tem = e.substring(0, e.length() - 1);
			}
			return INDENT_BLANKS + tem;
		}).reduce((a, b) -> a + "\n" + b).orElse(valueTem);
	}

	private static void formatPropertiesToYaml(List<String> yamlLineList, List<MyYamlNode> yamlNodes, Boolean lastNodeArrayFlag,
			String blanks) {
		Integer beforeNodeIndex = null;
		String equalSign;
		for (MyYamlNode yn : yamlNodes) {
			String value = yn.getValue();
			String remark = yn.getRemark();

			equalSign = SIGN_SEMICOLON;
			if (null == value || "".equals(value)) {
				value = "";
			} else {
				equalSign = SIGN_SEMICOLON + " ";
			}
			yn.resortValue();

			String name = yn.getName();
			if (lastNodeArrayFlag) {
				if (null == name) {
					yamlLineList.add(blanks + ARRAY_BLANKS + stringValueWrap(value));
				} else {
					if (null != beforeNodeIndex && beforeNodeIndex.equals(yn.getLastNodeIndex())) {
						yamlLineList.add(blanks + INDENT_BLANKS + name + equalSign + stringValueWrap(value));
					} else {
						yamlLineList.add(blanks + ARRAY_BLANKS + name + equalSign + stringValueWrap(value));
					}
				}
				beforeNodeIndex = yn.getLastNodeIndex();
			} else {
				// 父节点为空，表示，当前为顶层
				if (null == yn.getParent()) {
					String remarkTem = getRemarkProject(yn.getProjectRemark());
					if (!"".equals(remarkTem)) {
						yamlLineList.add(blanks + getRemarkProject(yn.getProjectRemark()));
					}
				}

				// 自己节点为数组，则添加对应的注释
				if (yn.getArrayFlag()) {
					if (null != remark && !"".equals(remark)) {
						yamlLineList.add(blanks + remark);
					}
				}
				yamlLineList.add(blanks + name + equalSign + stringValueWrap(value, remark));
			}

			if (yn.getArrayFlag()) {
				if (lastNodeArrayFlag) {
					formatPropertiesToYaml(yamlLineList, yn.getValueList(), true, INDENT_BLANKS + INDENT_BLANKS + blanks);
				} else {
					formatPropertiesToYaml(yamlLineList, yn.getValueList(), true, INDENT_BLANKS + blanks);
				}
			} else {
				if (lastNodeArrayFlag) {
					formatPropertiesToYaml(yamlLineList, yn.getChildren(), false, INDENT_BLANKS + INDENT_BLANKS + blanks);
				} else {
					formatPropertiesToYaml(yamlLineList, yn.getChildren(), false, INDENT_BLANKS + blanks);
				}
			}
		}
	}

	@SuppressWarnings("rawtypes")
	private static void formatYamlToProperties(List<String> propertiesLineList, Map<String, String> remarkMap, Object object,
			String prefix) {
		if (null == object) {
			return;
		}
		if (object instanceof Map) {
			// 填充注释
			if (remarkMap.containsKey(prefix)) {
				propertiesLineList.add(REMARK_PRE + remarkMap.get(prefix));
			}

			Map map = (Map) object;
			Set<?> set = map.keySet();
			for (Object key : set) {
				Object value = map.get(key);
				if (null == value) {
					value = "";
				}
				if (value instanceof Map) {
					formatYamlToProperties(propertiesLineList, remarkMap, value, prefixWithDOT(prefix) + key);
				} else if (value instanceof Collection) {
					Collection collection = (Collection) value;
					if (!collection.isEmpty()) {
						// 填充注释
						if (remarkMap.containsKey(prefixWithDOT(prefix) + key)) {
							propertiesLineList.add(REMARK_PRE + remarkMap.get(prefixWithDOT(prefix) + key));
						}

						Iterator<?> iterator = collection.iterator();
						int index = 0;
						while (iterator.hasNext()) {
							Object valueObject = iterator.next();
							formatYamlToProperties(propertiesLineList, remarkMap, valueObject,
									prefixWithDOT(prefix) + key + "[" + index + "]");
							index = index + 1;
						}
					}
				} else if (value instanceof String) {
					String valueStr = (String) value;
					valueStr = valueStr.trim();
					valueStr = valueStr.replace("\n", "\\\n");
					// 填充注释
					if (remarkMap.containsKey(prefixWithDOT(prefix) + key)) {
						propertiesLineList.add(REMARK_PRE + remarkMap.get(prefixWithDOT(prefix) + key));
					}

					propertiesLineList.add(prefixWithDOT(prefix) + key + SIGN_EQUAL + valueStr);
				} else {
					// 填充注释
					if (remarkMap.containsKey(prefixWithDOT(prefix) + key)) {
						propertiesLineList.add(REMARK_PRE + remarkMap.get(prefixWithDOT(prefix) + key));
					}

					propertiesLineList.add(prefixWithDOT(prefix) + key + SIGN_EQUAL + value);
				}
			}
		} else if (object instanceof Collection) {
			Collection collection = (Collection) object;
			if (!collection.isEmpty()) {
				// 填充注释
				if (remarkMap.containsKey(prefix)) {
					propertiesLineList.add(REMARK_PRE + remarkMap.get(prefix));
				}

				Iterator<?> iterator = collection.iterator();
				int index = 0;
				while (iterator.hasNext()) {
					Object valueObject = iterator.next();
					formatYamlToProperties(propertiesLineList, remarkMap, valueObject, prefix + "[" + index + "]");
					index = index + 1;
				}
			}
		} else if (object.getClass().isArray()) {
			Object[] array = (Object[]) object;
			for (int index = 0; index < array.length; index++) {
				formatYamlToProperties(propertiesLineList, remarkMap, array[index], prefix + "[" + index + "]");
			}
		} else if (object instanceof String) {
			String valueObject = (String) object;
			valueObject = valueObject.replace("\n", "\\\n");
			// 填充注释
			if (remarkMap.containsKey(prefix)) {
				propertiesLineList.add(REMARK_PRE + remarkMap.get(prefix));
			}

			propertiesLineList.add(prefix + SIGN_EQUAL + valueObject);
		} else {
			// 填充注释
			if (remarkMap.containsKey(prefix)) {
				propertiesLineList.add(REMARK_PRE + remarkMap.get(prefix));
			}

			propertiesLineList.add(prefix + SIGN_EQUAL + object);
		}
	}

	private static String prefixWithDOT(String prefix) {
		if ("".equals(prefix)) {
			return prefix;
		}
		return prefix + DOT;
	}

	private static String stringValueWrap(String value) {
		if (null == value || "".equals(value)) {
			return "";
		}
		// 对数组的数据进行特殊处理
		if (value.startsWith("[") && value.endsWith("]")) {
			return "'" + value + "'";
		}
		return value;
	}

	private static String stringValueWrap(String value, String remark) {
		if (null == value || "".equals(value)) {
			return "";
		}
		// 对数组的数据进行特殊处理
		if (value.startsWith("[") && value.endsWith("]")) {
			return "'" + value + "'" + getRemark(remark);
		}

		return value + getRemark(remark);
	}

	private static String getRemark(String remark) {
		if (null != remark && !"".endsWith(remark) && remark.startsWith("#")) {
			return " # " + remark.substring(1).trim();
		} else {
			return "";
		}
	}

	private static String getRemarkProject(String remark) {
		if (null != remark && !"".endsWith(remark) && remark.startsWith("#")) {
			return " # " + remark.substring(1).trim();
		} else {
			return "";
		}
	}
}